<template>
<div class="app-inner">
    <div id="container" v-if="logined">
        <div class="sider">
            <h3>当前在线</h3>
            <div class="user-list">
                <div class="user-item" v-for="(item, index) in users" :key="index">
                    <div class="user-name">{{item}} 
                        <span class="my-mark" v-if="currentUser === item">自己</span>
                        <span v-if="remoteUser === item" class="offering"></span>
                        </div>
                    <button class="call-btn" @click="callElseUser(item)">call</button>
                </div>
            </div>
        </div>
        <div class="video-area" :class="{'offering-video': remoteUser}">
            <video autoplay src="" ref="myVideo" class="myVideo"></video>
            <video autoplay src="" ref="targetUser" class="targetVideo">暂无接入</video>
            <div class="handler">
                <button class="stop" @click="stopOffer">stop offer</button>
            </div>
        </div>
        
    </div>
    <div class="wellcome-container" v-if="!logined">
        <h2 class="title">WellCome To Video Chat</h2>
        <div class="input-box">
            <input type="text" placeholder="请输入您的用户名" v-model="name" class="input-name">
        </div>
                <div class="join-btn" @click="handleJoin">Join in</div>
    </div>
  </div>
</template>


<style>
html,
body,
#app,
.app-inner {
    height: 100%;
}
.app-inner {
    display: flex;
    justify-content: center;
    align-self: center;
}
.wellcome-container {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-self: center;
    height: 200px;
}
input {
    padding: 4px 8px;
}
.input-box {
    margin: 12px 0;
}
.join-btn {
	width: 120px;
    height: 32px;
    margin: 12px auto;
    line-height: 32px;
    text-align: center;
    border-radius: 16px;
    background: green;
    color: #fff;
}

#container {
    display: flex;
    width: 100%;
    height: 500px;
}
* {
    box-sizing: border-box;
}
.sider {
    margin-right: 24px;
    width: 300px;
    padding: 12px;
    box-shadow: 0px 0px 2px #8f8f8f;
}
h3 {
    padding: 12px 0;
    border-bottom: 1px solid #cfcfcf;
}
.my-mark {
    padding: 2px 8px;
    background: #cfcfcf;
    font-size: 12px;
    border-radius: 12px;
}
.offering {
    position: absolute;
    right: 0;
    top: 0;
    transform: translateX(80%);
    width: 10px;
    height: 10px;
    border-radius: 5px;
    background: greenyellow;
}
.user-name {
    position: relative;
}
.user-item {
    display: flex;
    justify-content: space-between;
    padding: 12px;
}
.call-btn {
    background:  lightgreen;
    color: #fff;
    border: none;
    padding: 4px 12px;
    border-radius: 12px;
    transition: transform .5s;
    outline: none;
}
.call-btn:hover {
    transform: scale(1.2);
}
.video-area {
    position: relative;
    width: 500px;
    height: 500px;
}
.handler {
    position: absolute;
    z-index: 5;
    right: 12px;
    bottom: 0;
}
.stop {
    padding: 6px 12px;
    background: #fff;
}
video {
    position: absolute;
    right: 0;
    top: 0;
    z-index: 2;
    width: 100%;
    height: 100%;
}
.video-area.offering-video .myVideo{
    z-index: 3;
    width: 160px;
    height: 160px;
}
</style>

<script>
navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
window.RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.webkitRTCIceCandidate;
window.RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription;

let ws = null;
let Pc = null;

export default {
    data() {
        return {
            logined: false,
            name: '',    // 用户登陆名
            users: ['test', 'memory'],       // 所有在线用户
            currentUser: '', // 当前用户
            remoteUser: ''   // 正在视频会议用户
        }
    },
    mounted() {
        this.currentUser = window.sessionStorage.getItem('webRTC_current_name');

         ws = new WebSocket(`wss://${location.hostname}:10000`);

        ws.onopen = (e) => {
            console.log('ws is open');
            
        }

        ws.onmessage =  (ev) => {
            let data = JSON.parse(ev.data);
            console.log(data)
            const type = data.type;
            const funcName = 'mHandle' + type[0].toUpperCase() + type.slice(1);
            const func = this[funcName];
            typeof func === 'function' && func(data);
        }
        ws.onerror = (err) => {
            ws.close();
        }
        ws.onclose = function () {
            console.log('ws is close');
        }

        if(this.currentUser) {
            this.init();
        }
    },
    beforeDestroy() {
        this.stopOffer();
        ws.close();
    },
    methods: {
        init() {
           this.getUserMedia((stream) => {
                this.myStream = stream;
                this.startClient();
            })

            
        },
        handleJoin() {
            const {name} = this;
			if (!name.trim().length) {
				return alert('请输入你的名字');
            }
            this.currentUser = name;

            this.send({
                type: 'login'
            });
        },
        send(message){
            if (this.currentUser === this.remoteUser) {
                return alert('自己跟自己有什么好聊的？')
            }
            message.fromUser = this.currentUser;
            ws.send(JSON.stringify(message));
        },
        getUserMedia(cb) {
            navigator.mediaDevices.getUserMedia({
                video: true,
                audio: true
            }).then((stream) => {
                this.$refs.myVideo.src = URL.createObjectURL(stream);
                this.streamTrack = stream.getTracks()[0];
                cb(stream);
            }).catch(function(err) {
                console.log('设备不支持多媒体');
            });
        },
        startClient() {
            const stream = this.myStream;
            var iceServer = {
                "iceServers": [{
                    "url": "stun:stun.l.google.com:19302"
                }]
            };

            Pc = new window.RTCPeerConnection(iceServer);
            Pc.addStream(stream);
            Pc.onaddstream = (e) => {
                console.log('流媒体添加。。。')
                this.$refs.targetUser.src =  URL.createObjectURL(e.stream);
                this.remoteStream = e.stream;
            }
            Pc.onicecandidate = (e) => {
                console.log(e.candidate)
                if (e.candidate) {
                    console.log('添加candidate。。。。')
                    this.send({
                        type: 'candidate',
                        candidate: e.candidate,
                        remoteUser: this.remoteUser
                    })
                }
            }
        },
        setOffer(offer, fromUser) {
            this.remoteUser = fromUser;
            Pc.setRemoteDescription(new RTCSessionDescription(offer));
            Pc.createAnswer((answer) => {
                this.send({
                    type: 'answer',
                    answer,
                    remoteUser: fromUser
                });
                console.log('发送应答')
                Pc.setLocalDescription(answer);
            }, () => {
                alert('创建应答失败')
            })
        },
        stopOffer() {
            if (this.remoteUser) {
                Pc.close();
                Pc = null;
                this.send({
                    type: 'stopOffer',
                    remoteUser: this.remoteUser
                });
                this.remoteUser = '';
                this.$refs.targetUser.src = '';
                this.startClient();
            }
        },
        createOffer() {
            Pc.createOffer((offer) => {
                this.send({
                    type: 'offer',
                    offer,
                    remoteUser: this.remoteUser
                });

                Pc.setLocalDescription(offer);
            }, () => {
                alert('创建信令失败');
            }, {
                mandatory: {
                    OfferToReceiveAudio: true
                }
            })
        },
        callElseUser(targetUser) {
            if (this.remoteUser) {
                return alert('请先关闭与他人的视频会议');
            }
            
            const isSelf = this.currentUser === targetUser;
            if(isSelf) {
                alert('疯狂为自己打call...');
            } else {
                this.remoteUser = targetUser;
                console.log(targetUser)
                this.send({
                    type: 'checkLogin',
                    remoteUser: targetUser
                });
            }
        },
        mHandleLogin(data) {
            if (data.success) {
                this.logined = true;
                window.sessionStorage.setItem('webRTC_current_name', name);
                this.init();
            } else {
                alert('此用户名已在线，请换其他用户名');
            }
        },
        mHandleCheckLogin(data) {
            if (data.isLogin) {
                this.createOffer();
            } else {
                alert('用户未登录');
            }
        },
        mHandleOffer(data) {
            if (confirm('你收到视频会议，确定参加么？')) {
                this.setOffer(data.offer, data.fromUser);
            } else {
                alert('你取消了视频会议应答');
            }
        },
        mHandleAnswer(data) {
            console.log('应答')
            console.log(data)
            Pc.setRemoteDescription(new RTCSessionDescription(data.answer));
        },
        mHandleCandidate(data) {
            console.log('candidate')
            console.log(data)
            Pc.addIceCandidate(new RTCIceCandidate(data.candidate));
        },
        mHandleUnline(data) {
            alert('用户不在线')
        },
        mHandleLeave(data) {
            console.log(data.fromUser + '离开了');
            console.log('我当前链接的是他么？ ： ' + (data.fromUser === this.remoteUser))
            if (data.fromUser === this.remoteUser) {
                this.stopOffer();
            }
        },
        mHandleJoin(data) {
            const {fromUser, users} = data;
            console.log(fromUser + ' is  join');
            this.users = users;
        },
        mHandleStopOffer(data) {
            console.log(data.fromUser + ' stop the offer');
            if (data.fromUser === this.remoteUser) {
                this.stopOffer();
            }
        }
    }
}
</script>

